import requests
import json
import logging
import traceback

from rest_framework import viewsets, mixins, exceptions
from rest_framework.decorators import action
from connection.models import Partner
from connection.serializers import PartnerSerializer
from connection.filters import PartnerFilter
from connection.services import connection_service, certificate_service
from libs.decorators import permission_required
from libs.simple_responses import api_success
from libs.enums import Permission, PartnerType


class PartnerViewSet(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.UpdateModelMixin):
    queryset = Partner.objects.all().order_by('-id')
    serializer_class = PartnerSerializer
    filterset_class = PartnerFilter
    ordering_fields = ('id',)

    @permission_required([Permission.ORGANIZATION_MANAGE.value])
    def update(self, request, *args, **kwargs):
        return super().update(request, *args, **kwargs)

    @permission_required([Permission.ORGANIZATION_MANAGE.value])
    def partial_update(self, request, *args, **kwargs):
        return super().partial_update(request, *args, **kwargs)

    @action(methods=['post'], detail=True, url_path='enter')
    def enter(self, request, *args, **kwargs):
        partner = self.get_object()
        if partner.type != PartnerType.APP.value:
            raise exceptions.ValidationError({'error': '未知应用'})
        connection = connection_service.get_connection_by_partner_id(partner.id)
        if not connection:
            raise exceptions.ValidationError({'error': '未知应用'})
        server = partner.app_server
        headers = {}
        certificate = connection_service.get_other_side_certificate(connection.id)
        if certificate:
            server, headers = certificate_service.get_server_and_headers(certificate.data)
        api = f'{server}/openapi/auth/enter'
        try:
            response = requests.post(api, headers=headers)
            if response.status_code != 200:
                raise exceptions.ValidationError({'error': '应用异常'})
            data = json.loads(response.content)
            if not data.get('url'):
                raise exceptions.ValidationError({'error': '应用响应格式有误'})
            result = {
                'url': data.get('url')
            }
            return api_success(data=result)
        except Exception:
            logging.getLogger().info(f'跳转应用时对方接口响应异常, 应用id: {partner.id}, error: {traceback.format_exc()}')
            raise exceptions.ValidationError({'error': '应用异常'})
